package com.atguigu.gulimall.order.config;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @Description :用于RabbitMQ的配置交换机，队列，绑定队列等
 * 根据事先准备好的思维图进行
 * @Author : mayp
 * @Date: 2021-01-19 15:24
 */
@Configuration
public class MyMQConfig {
    public static final String ORDER_DELAY_QUEUE="order.delay.queue"; //死信队列名称
    public static final String ORDER_RELEASE_ORDER_QUEUE="order.release.order.queue"; //普通队列名称
    public static final String ORDER_EVENT_EXCHANGE="order-event-exchange"; //交换机名称
    public static final String ORDER_CREATE_ORDER = "order.create.order"; //死信路由键
    public static final String ORDER_RELEASE_ORDER = "order.release.order"; //死信路由键
    /**
     * 延迟队列（死信队列）
     * 这个队列里面如果过了一段时间以后，就会死掉，会发送给死信队列的交换机
     * 一旦RabbitMQ创建好相应的队列以后，只要有队列，即使代码上的属性修改了，也不会覆盖到mq，
     *  那么就直接去MQ上删除相应的队列即可
     * @return
     */
    @Bean
    public Queue orderDelayQueue(){
        Map<String,Object> arguments = new HashMap<>();
        arguments.put("x-dead-letter-exchange",ORDER_EVENT_EXCHANGE);//死信路由
        arguments.put("x-dead-letter-routing-key",ORDER_RELEASE_ORDER); //死信路由键
        arguments.put("x-message-ttl",180000); //消息过期时间，毫秒为单位3分钟后
//        String name, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments
//        参数作用：队列名称， 是否持久化，是否只有一个连接的话，其他就不要连接，是否自动删除，还可以创建其他参数
        Queue queue = new Queue(ORDER_DELAY_QUEUE,true,false,false,arguments);
        return queue;
    }

    /**
     * 普通队列
     * @return
     */
    @Bean
    public Queue orderReleaseOrderQueue(){
        return new Queue(ORDER_RELEASE_ORDER_QUEUE,true,false,false);
    }

    /**
     * 交换机(需要与上面两个队列进行绑定)
     * @return
     */
    @Bean
    public Exchange orderEventExchange(){
//        String name, boolean durable, boolean autoDelete, Map<String, Object> arguments
//        字符串名称，持久性，自动删除，参数
        return new TopicExchange(ORDER_EVENT_EXCHANGE,true,false);
    }

    /**
     * 绑定关系1（与死信队列绑定）
     */
    @Bean
    public Binding orderCreateOrderBinding(){
       //                       目的地                        目的地的类型             哪个交换机         路由键
       // public Binding(String destination, DestinationType destinationType, String exchange, String routingKey,
       //                   是否有其他参数属性
       // 	Map<String, Object> arguments)
       return new Binding(ORDER_DELAY_QUEUE,
                    Binding.DestinationType.QUEUE,
                    ORDER_EVENT_EXCHANGE,
                    ORDER_CREATE_ORDER,
                    null);
    }

    /**
     * 绑定关系2（与普通队列绑定）
     */
    @Bean
    public Binding orderReleaseOrderBinding(){
        return new Binding(ORDER_RELEASE_ORDER_QUEUE,
                    Binding.DestinationType.QUEUE,
                    ORDER_EVENT_EXCHANGE,
                    ORDER_RELEASE_ORDER,
                    null);
    }

    /**
     * 订单释放直接和库存释放进行绑定
     * @return
     */
    @Bean
    public Binding orderReleaseOtherBinding(){
        return new Binding("stock.release.stock.queue",
                Binding.DestinationType.QUEUE,
                ORDER_EVENT_EXCHANGE,
                "order.release.other.#",
                null);
    }

    /**
     * 订单的秒杀单的监听队列
     * 结合了消息队列MQ，此时在这一块倒不是来做最终一致性，虽然也是要保证最终一致，由订单服务要真正的去创建订单，在数据库粒保存
     * 但是此次更多做的是流量的削峰
     * 请求一进来，不用立即去调用订单服务，直接放到MQ消费队列里面，然后让订单服务慢慢去消费就不至于把订单服务打垮
     */
    @Bean
    public Queue orderSeckillOrderQueue(){
        return new Queue("order.seckill.order.queue",true,false,false);
    }

    @Bean
    public Binding orderSeckillOrderQueueBinding(){
        return new Binding("order.seckill.order.queue",
                Binding.DestinationType.QUEUE,
                "order-event-exchange",
                "order.seckill.order",
                null);
    }
}
